package com.ling.fireworks.ui.pages.main.mvi

import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.lifecycle.viewModelScope
import com.ling.fireworks.base.IUiEvent
import com.ling.fireworks.base.IViewModel
import com.ling.fireworks.model.Firework
import com.ling.fireworks.model.Particle
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlin.math.PI
import kotlin.math.cos
import kotlin.math.sin
import kotlin.random.Random

/**
 * @author Ling
 * @date :2025/9/15 14:10
 */
class MainViewModel : IViewModel<MainIntent, MainState, IUiEvent>() {

    private var startJob : Job? = null

    init {
        start()
    }

    override fun initUiState() = MainState()

    override fun handleIntent(intent: MainIntent) {
        when(intent){
            is MainIntent.Launch -> createFirework(intent.position)
            is MainIntent.Clear -> updateUiState { copy(fireworks = arrayListOf()) }
        }
    }

    private fun start(){
        stop()
        startJob = viewModelScope.launch {
            while (isActive){
                updateFireworks()
                delay(16) //60fps
            }
        }
    }

    private fun stop(){
        updateUiState { copy(fireworks = arrayListOf()) }
        startJob?.cancel()
    }

    private fun createFirework(position: Offset) {
        val particleCount = 100 + Random.nextInt(100)
        val color = Color.hsl(Random.nextFloat() * 360f, 1f, 0.7f)
        updateUiState { copy(fireworks = uiState.value.fireworks.apply {
            add(Firework(
                particles = List(particleCount) {
                    val angle = Random.nextFloat() * 2f * PI.toFloat()
                    val speed = 2f + Random.nextFloat() * 5f
                    Particle(
                        position = position,
                        velocity = Offset(cos(angle) * speed, sin(angle) * speed),
                        size = 3f + Random.nextFloat() * 5f,
                        alpha = 0.9f + Random.nextFloat() * 0.1f
                    )
                },
                color = color
            ))
        }) }
    }

    private fun updateFireworks() {
        val currentTime = System.currentTimeMillis()
        val updatedFireworks = uiState.value.fireworks.map { firework ->
            val updatedParticles = firework.particles.map { particle ->
                if (particle.life > 0) {
                    val newVelocity = particle.velocity * 0.98f
                    particle.copy(
                        position = particle.position + newVelocity,
                        velocity = newVelocity,
                        life = particle.life - 0.01f
                    )
                } else {
                    particle
                }
            }
            firework.copy(particles = updatedParticles)
        }

        updateUiState { copy(fireworks = arrayListOf()) }
        updateUiState {
            copy(fireworks = arrayListOf<Firework>().apply {
                addAll(
                    updatedFireworks.filter {
                        currentTime - it.launchTime <= 3000 && it.particles.any { p -> p.life > 0 }
                    }
                )
            })
        }
    }

    override fun onCleared() {
        super.onCleared()
        stop()
    }
}